from rest_framework import serializers
from myadmin.models import Role, Admin, Resource, Interface, ResourceMutex, Department, Position


class RoleSerializer(serializers.ModelSerializer):
    # p_resources = serializers.SerializerMethodField() # 父资源
    # resources_name = serializers.SerializerMethodField() # 子资源

    # 总资源名字和id
    all_resources = serializers.SerializerMethodField(read_only=True)
    all_resources_id = serializers.SerializerMethodField(read_only=True)

    # 使用位运算新建用户时传入的权限列表
    resources_id_list = serializers.ListField(child=serializers.CharField(), write_only=True)

    class Meta:
        model = Role
        fields = '__all__'

    def create(self, validated_data):
        name = validated_data.get('name')
        type = validated_data.get('type')

        # 使用角色-资源表创建角色
        # 该字段在位运算前为资源表的外键列表字段，使用位运算后为权限的id列表字段
        resources = validated_data.get('resources')

        # 总权限
        s_resources = [i.id for i in resources]
        print("子权限：", s_resources)

        # 父权限
        p_role = validated_data.get('pid', None)
        # 判断创建的是否是父级管理员
        if p_role:
            pid = p_role.id
            print(pid)
            role = Role.objects.get(id=pid)
            role_data = RoleSerializer(role).data
            p_resources = role_data.get("resources")
            print("父权限：", p_resources)
            # 子权限
            resources_list = list(set(s_resources) - set(p_resources))
        else:
            resources_list = s_resources

        # 判断子权限是否有互斥内容
        mutex_resources = ResourceMutex.objects.filter(resource1_id__in=resources_list)
        mutex_list = [i.resource2_id for i in mutex_resources]
        print("互斥对应列表：", mutex_list)
        # 两列表取交集
        result = list(set(mutex_list) & set(resources_list))
        print("互斥结果：", result)
        # 如果结果不为空，说明有互斥内容，报错
        if result:
            # 报错
            raise serializers.ValidationError('资源互斥，请重新选择')

        # ---------------------------------------------------------

        # 位运算获取资源
        # 获取前端传来的资源id列表
        resources_id_list = validated_data.get("resources_id_list")
        print(resources_id_list)

        # 首先通过资源id表去互斥表查询，有无互斥资源
        mutex_resources = ResourceMutex.objects.filter(resource1_id__in=resources_id_list)
        mutex_list = [item.resource2_id for item in mutex_resources]
        result = list(set(mutex_list) & set(resources_id_list))
        if result:
            raise serializers.ValidationError("资源互斥，请重新选择")

        # 获取总资源权限值
        # 通过资源id列表获取资源模型对象集
        resources = Resource.objects.filter(id__in=resources_id_list)
        # 获取前端传来的权限列表
        permission_list = [item.id for item in resources]
        # 获取权限列表中权限对应的权限值，并加到用户权限中
        all_permission = 0
        for i in permission_list:
            permission_value = Resource.objects.get(id=i).permission
            all_permission = all_permission | permission_value

        admin_permission = all_permission

        # 如果有父角色，则减去父角色权限值，注意使用^符
        if p_role:
            p_role_permission = p_role.permission
            admin_permission = all_permission ^ p_role_permission

            # 创建角色及资源
        role = Role.objects.create(name=name,
                                   pid=p_role,
                                   type=type,
                                   permission=admin_permission
                                   )
        role.resources.set(resources_list)
        return role

    # # 获取角色父资源
    # def get_p_resources(self, obj):
    #     resources = ResourceSerializer(obj.pid.resources.all(), many=True).data
    #     return [resource['name'] for resource in resources]
    #
    # 获取角色特有的资源
    # def get_resources_name(self, obj):
    #     resources = ResourceSerializer(obj.resources.all(), many=True).data
    #     return [resource['name'] for resource in resources]

    # ---------------------------------------------------------------

    # 通过角色-资源表获取资源
    # 获取所有资源名字
    # def get_all_resources(self, obj):
    #     role_resources = ResourceSerializer(obj.resources.all(), many=True).data
    #     role_resources_list = [resource['name'] for resource in role_resources]
    #     if obj.pid:
    #         p_resources = ResourceSerializer(obj.pid.resources.all(), many=True).data
    #         p_resources_list = [resource['name'] for resource in p_resources]
    #         all_resources = list(set(p_resources_list + role_resources_list))
    #         return all_resources
    #     else:
    #         return role_resources_list

    # 获取所有资源id
    # def get_all_resources_id(self, obj):
    #     role_resources = ResourceSerializer(obj.resources.all(), many=True).data
    #     role_resources_list = [resource['id'] for resource in role_resources]
    #     if obj.pid:
    #         p_resources = ResourceSerializer(obj.pid.resources.all(), many=True).data
    #         p_resources_list = [resource['id'] for resource in p_resources]
    #         all_resources = list(set(p_resources_list + role_resources_list))
    #         return all_resources
    #     else:
    #         return role_resources_list

    # ---------------------------------------------------------------------------------

    # 通过资源权限值获取资源
    # 获取所有资源名字
    def get_all_resources(self, obj):
        # 获取用户权限值
        role_permission = obj.permission
        print(role_permission)
        # 获取父级权限值
        if obj.pid:
            p_role_permission = obj.pid.permission
            role_permission += p_role_permission
        # 获取所有资源
        resource = Resource.objects.exclude(permission=None)
        resource_name_list = []
        # 获取用户权限值对应的资源
        for item in resource:
            # 如果资源权限值大于用户权限值，则结束寻找
            if item.permission > role_permission:
                break
            if (role_permission & item.permission) > 0:
                resource_name_list.append(item.name)
        return resource_name_list

    # 获取所有资源id
    def get_all_resources_id(self, obj):
        # 获取用户权限值
        role_permission = obj.permission
        # 获取父级权限值
        if obj.pid:
            p_role_permission = obj.pid.permission
            role_permission += p_role_permission
        # 获取所有资源
        resource = Resource.objects.exclude(permission=None)
        resource_id_list = []
        # 获取用户权限值对应的资源
        for item in resource:
            # 如果资源权限值大于用户权限值，则结束寻找
            if item.permission > role_permission:
                break
            if (role_permission & item.permission) > 0:
                resource_id_list.append(item.id)
        return resource_id_list


class AdminSerializer(serializers.ModelSerializer):
    class Meta:
        model = Admin
        fields = '__all__'


class ResourceSerializer(serializers.ModelSerializer):
    pname = serializers.CharField(source='pid.name', read_only=True)

    class Meta:
        model = Resource
        fields = '__all__'


class InterfaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Interface
        fields = '__all__'


class ResourceMutexSerializer(serializers.ModelSerializer):
    class Meta:
        model = ResourceMutex
        fields = '__all__'

class DepartmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Department
        fields = '__all__'

class PositionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Position
        fields = '__all__'
